package com.xpalive.base.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.xpalive.base.dto.page.MyBatisPageAdapter;
import com.xpalive.base.dto.page.PageReq;
import com.xpalive.base.dto.page.PageRsp;
import com.xpalive.base.mapper.MyBaseMapper;
import com.xpalive.exception.BizException;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.springframework.transaction.annotation.Transactional;

public interface MyBaseService<T> extends IService<T> {

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean removePermanentById(Serializable id) {
        return SqlHelper.retBool(getMyBaseMapper().delPermanentById(id));
    }

    /**
     * 根据 columnMap 条件，删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean removePermanentByMap(Map<String, Object> columnMap) {
        Assert.notEmpty(columnMap, "error: columnMap must not be empty");
        return SqlHelper.retBool(getMyBaseMapper().delPermanentByMap(columnMap));
    }

    /**
     * 根据 entity 条件，删除记录
     *
     * @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean removePermanent(Wrapper<T> queryWrapper) {
        return SqlHelper.retBool(getMyBaseMapper().delPermanent(queryWrapper));
    }

    /**
     * 删除（根据ID 批量删除）
     *
     * @param idList 主键ID列表
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean removePermanentByIds(Collection<? extends Serializable> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return false;
        }
        return SqlHelper.retBool(getMyBaseMapper().delPermanentBatchIds(idList));
    }

    /**
     * 获取对应 entity 的 BaseMapper
     *
     * @return BaseMapper
     */
    MyBaseMapper<T> getMyBaseMapper();

    /**
     * 翻页查询
     *
     * @param pageReq      翻页对象
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
    default PageRsp<T> page(PageReq pageReq, Wrapper<T> queryWrapper) {
        IPage<T> convert = MyBatisPageAdapter.convert(pageReq);
        IPage<T> page = getBaseMapper().selectPage(convert, queryWrapper);
        return MyBatisPageAdapter.convert(page);
    }

    /**
     * 无条件翻页查询
     *
     * @param pageReq 翻页对象
     * @see Wrappers#emptyWrapper()
     */
    default PageRsp<T> page(PageReq pageReq) {
        return page(pageReq, Wrappers.emptyWrapper());
    }

    /**
     * @param oldList     数据库查询出的数据
     * @param newList     新的数据
     * @param getIdentity 数据对比的唯一标识字段
     * @param <R>
     */
    <R> void updateRef(List<T> oldList, List<T> newList, Function<T, R> getIdentity);

    /**
     * @param oldList     数据库查询出的数据
     * @param newList     新的数据
     * @param getIdentity 数据对比的唯一标识字段
     * @param <R>
     */
    <R> void updateRef(List<T> oldList, List<T> newList, Function<T, R> getIdentity,
        Function<T, LambdaUpdateWrapper<T>> updateWrapper);

    /**
     * 更新
     *
     * @param entity 实体
     */
    @Transactional(rollbackFor = Exception.class)
    default T saveEntity(T entity) {
        if (!save(entity)) {
            throw new BizException("新增失败");
        }
        return entity;
    }

    /**
     * 更新
     *
     * @param entity 实体
     */
    @Transactional(rollbackFor = Exception.class)
    default T updateEntity(T entity) {
        if (!updateById(entity)) {
            throw new BizException("更新失败");
        }

        return entity;
    }

    /**
     * 查询分页
     * @param page
     * @param query
     * @param biFunction
     * @param <R>
     * @param <Query>
     * @return
     */
    default <R, Query> PageRsp<R> page(PageReq page, Query query,
        BiFunction<IPage<R>, Query, IPage<R>> biFunction) {
        IPage<R> convert = MyBatisPageAdapter.convert(page);
        return MyBatisPageAdapter.convert(biFunction.apply(convert, query));
    }
}
